package py.com.erpone.session.almacen;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.LocalBean;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

import org.primefaces.context.RequestContext;

import py.com.erpone.entity.almacen.Lote;
import py.com.erpone.entity.almacen.LoteDetalle;
import py.com.erpone.entity.dm.Inventario;
import py.com.erpone.entity.dm.OrdenCompra;
import py.com.erpone.entity.dm.Producto;
import py.com.erpone.session.almacen.list.LoteList;
import py.com.erpone.session.dm.list.OrdenCompraList;
import py.com.erpone.util.LocaleSelector;
import py.com.erpone.view.datamodel.LoteModel;
import py.com.erpone.view.datamodel.OrdenCompraModel;


@Stateful
@Named
@LocalBean
@ConversationScoped
public class LoteBean {

	@PersistenceContext(type=PersistenceContextType.EXTENDED)
	private EntityManager em;

	@Inject
	private LocaleSelector localeSelector;

	private OrdenCompraModel ordenCompraModel;
	private LoteModel loteModel;
	@Inject
	private LoteList loteList;

	@Inject
	private OrdenCompraList ordenCompraList;


	@Inject
	private Conversation conversation;

	private Lote lote;

	//DETAIL
	private Producto producto = new Producto();
	private LoteDetalle lotesDetalles = new LoteDetalle();
	private boolean disableImportar = false;
	private boolean disableManual = false;
	private Date currentDate;



	public Date getCurrentDate() {
		return currentDate;
	}

	public void setCurrentDate(Date currentDate) {
		this.currentDate = currentDate;
	}

	public OrdenCompraModel getOrdenCompraModel() {
		return ordenCompraModel;
	}

	public void setOrdenCompraModel(OrdenCompraModel ordenCompraModel) {
		this.ordenCompraModel = ordenCompraModel;
	}

	public LoteModel getLoteModel() {
		return loteModel;
	}

	public void setLoteModel(LoteModel loteModel) {
		this.loteModel = loteModel;
	}

	public void setLote(Lote lote) {
		this.lote = lote;
	}

	public void setProducto(Producto producto) {
		this.producto = producto;
	}

	public void setLotesDetalles(LoteDetalle lotesDetalles) {
		this.lotesDetalles = lotesDetalles;
	}

	public Lote getLote() {
		return lote;
	}

	public Producto getProducto() {
		return producto;
	}

	public LoteDetalle getLotesDetalles() {
		return lotesDetalles;
	}


	public boolean getDisableImportar() {
		return disableImportar;
	}

	public void setDisableImportar(boolean disableImportar) {
		this.disableImportar = disableImportar;
	}

	public boolean getDisableManual() {
		return disableManual;
	}

	public void setDisableManual(boolean disableManual) {
		this.disableManual = disableManual;
	}

	@PostConstruct
	public void postConstruct(){
		ordenCompraModel = new OrdenCompraModel(ordenCompraList.ImportarARecepcionPedido());
		loteModel = new LoteModel(loteList.ImportarAVerificacion());
		Calendar now = GregorianCalendar.getInstance();
		setCurrentDate(now.getTime());
	}

	public void iniciar(){
		if(conversation.isTransient())
			conversation.begin();

		lote=new Lote();
		lote.setId(0l);
		lote.setLoteDetalle(new ArrayList<LoteDetalle>());
		//para testes
		lote.setSituacion(lote.SITUACION_RECIBIDO);

		lote.setFecha(getCurrentDate());
		lotesDetalles = new LoteDetalle();
		lotesDetalles.setId(0L);
		lotesDetalles.setLote(lote);
		lote.setOrdenCompra(new OrdenCompra());

	}

	public void iniciar(Lote lote){
		if(conversation.isTransient())
			conversation.begin();
		if(lote.getSituacion().equals(lote.SITUACION_FINALIZADO)){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, localeSelector.getMensaje("comun.error.situacion"), lote.getSituacionExtenso()));
			RequestContext.getCurrentInstance().execute("dlg.hide()");
			RequestContext.getCurrentInstance().update("frmPrincipalRP");
			return;
		}
		this.lote=lote;
	}

	public HashMap<String, String> getSituaciones() {
		if(lote == null)return null;
		HashMap<String, String> retorno = new HashMap<String, String>();
		Map<String, String> map = lote.getListSituacion();
		for (Map.Entry<String, String> entry : map.entrySet()){
			retorno.put(localeSelector.getMensaje("situacion."+entry.getKey()), entry.getValue());
		}
		return retorno;
	}

	public String getSituacionExtenso(String key, HashMap<String, String> listSituacion) {
		String retorno = key;
		Map<String, String> map = listSituacion;
		for (Map.Entry<String, String> entry : map.entrySet()){
			if(key.equals(entry.getKey()))
				retorno = localeSelector.getMensaje("situacion."+entry.getKey());
		}
		return retorno;
	}
	public void guardar(){
		try {
			if(lote.getId()==0){
				List<LoteDetalle> list = new ArrayList<LoteDetalle>();
				if(lote.getLoteDetalle()!=null){
					list = lote.getLoteDetalle();
					lote.setLoteDetalle(null);
				}
				OrdenCompra oc = null;
				if(lote.getOrdenCompra() != null){
					oc = lote.getOrdenCompra();
					lote.setOrdenCompra(null);
				}
				em.persist(lote);
				if(oc != null)
					lote.setOrdenCompra(oc);
				//lote = em.find(Lote.class, lote.getId());
				if(!list.isEmpty()){
					for (LoteDetalle loteDetalle : list) {
						loteDetalle.setLote(lote);
					}
					lote.setLoteDetalle(list);
					em.merge(lote);
				}else if(oc != null)
					em.merge(lote);
			    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, localeSelector.getMensaje("comun.exito.creado"), String.valueOf(lote.getId())));
			}else{
				em.merge(lote);
	            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, localeSelector.getMensaje("comun.exito.actualizado"), String.valueOf(lote.getId())));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		 //El dialog solo se cierra si la lista de contactos y todos los demás campos se completaron
		  //Se mezcla la lógica de negocio con la vista (xhtml), buscar otra alternativa
		  RequestContext rc = RequestContext.getCurrentInstance();
		  rc.execute("dlgLote.hide()");
		  RequestContext.getCurrentInstance().update("frmPrincipalRP");
	}

	public void eliminar(Lote lote){
		if(lote.getSituacion().equals(lote.SITUACION_FINALIZADO)){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, localeSelector.getMensaje("comun.error.situacion"), lote.getSituacionExtenso()));
			RequestContext.getCurrentInstance().update("frmPrincipalRP");
			return;
		}
		if(lote.getSituacion().equals(lote.SITUACION_RECIBIDO)){
			if(lote.getOrdenCompra() != null){
				OrdenCompra oc = lote.getOrdenCompra();
				oc.setSituacion(oc.SITUACION_ABIERTO);//TODO no es correcto porque tambien su situacion anterior podria haber sido pagado y no abierto
				em.remove(em.merge(lote));
				em.merge(oc);
			}else
				em.remove(lote);
		}else{
			//VERIFICACION
			lote.setSituacion(lote.SITUACION_RECIBIDO);//vuelve nuevamente a recibido
			for (LoteDetalle item : lote.getLoteDetalle()) {
				Inventario i = loteList.findInventario(item);
				if(i == null){//No deberia haber ningun null en eliminar se supone que siempre existira el registro de inventario
					i = new Inventario();
					i.setAlmacen(lote.getAlmacen());
					i.setProducto(item.getProducto());
				}
				i.setExistencia(i.getExistencia()!=null?i.getExistencia()-item.getCantidadVerificada():0);
				i.setLoteDetalle(item);
				if(i.getId()>0)
					em.merge(i);
				else
					em.persist(i);
			}
			em.merge(lote);
		}

		FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, localeSelector.getMensaje("comun.exito.eliminado"), String.valueOf(lote.getId())));
		if(!conversation.isTransient())
			conversation.end();
	}

	public String cancelar(){
		if(!conversation.isTransient())
			conversation.end();
		if(lote.getSituacion().equals(lote.SITUACION_RECIBIDO))
			return "/almacen/recepciones.xhtml";
		else
			return "/almacen/verificaciones.xhtml";
	}

	public void agregar(){
		//lotesDetalles.setLote(lote);
		if(lote != null && lote.getId() > 0)
			lotesDetalles.setLote(lote);
		LoteDetalle ld = new LoteDetalle();
		ld.setCantidadDevuelta(lotesDetalles.getCantidadDevuelta());
		ld.setCantidadRecibida(lotesDetalles.getCantidadRecibida());
		ld.setCantidadSolicitada(lotesDetalles.getCantidadSolicitada());
		ld.setCantidadVerificada(lotesDetalles.getCantidadVerificada());
		ld.setFecha(lotesDetalles.getFecha());
		ld.setLote(lote);
		ld.setLoteNumero(lotesDetalles.getLoteNumero());
		ld.setPatrimonio(lotesDetalles.getPatrimonio());
		ld.setProducto(lotesDetalles.getProducto());
		ld.setSituacion(lotesDetalles.getSituacion());
		ld.setVencimiento(lotesDetalles.getVencimiento());
		lote.getLoteDetalle().add(ld);
		setDisableImportar(true);
		lotesDetalles = new LoteDetalle();
		//RequestContext.getCurrentInstance().update(":frm_RP:panelRP:formButtons");

	}

	public void showMessageIfSelected(){
		if(lote.getOrdenCompra() != null && lote.getOrdenCompra().getId() > 0){
			lote.setProveedor(lote.getOrdenCompra().getSolicitudCotizacion().getProveedor());
		    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, localeSelector.getMensaje("comun.exito.importado.lotenumero"), ""));
		    setDisableManual(true);
		    RequestContext.getCurrentInstance().update(":frm_RPI");
		}
	}

	//VERIFICACION
	public void iniciarVerificacion(){
		if(conversation.isTransient())
			conversation.begin();

		lote=new Lote();
		lote.setId(0l);
		lote.setLoteDetalle(new ArrayList<LoteDetalle>());
		//para testes
		lote.setSituacion(lote.SITUACION_VERIFICADO);
		Calendar now = GregorianCalendar.getInstance();
		lote.setFecha(now.getTime());
		lotesDetalles = new LoteDetalle();
		lotesDetalles.setId(0L);
	}

	public void guardarVerificacion(){
		try {
			for (LoteDetalle item : lote.getLoteDetalle()) {
				Inventario i = loteList.findInventario(item);
				if(i == null)
					i = new Inventario();
				i.setAlmacen(lote.getAlmacen());
				i.setProducto(item.getProducto());
				i.setExistencia(i.getExistencia()!=null?i.getExistencia()+item.getCantidadVerificada():item.getCantidadVerificada());
				i.setLoteDetalle(item);
				if(i.getId()>0)
					em.merge(i);
				else
					em.persist(i);
			}

			em.merge(lote);
		    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, localeSelector.getMensaje("comun.exito.creado"), String.valueOf(lote.getId())));
		} catch (Exception e) {
			e.printStackTrace();
		}
		RequestContext rc = RequestContext.getCurrentInstance();
		rc.execute("dlgLote.hide()");
		RequestContext.getCurrentInstance().update("frmPrincipalRP");
	}

	public void showMessageIfRecepcionIsSelected(){
		if(lote != null && lote.getSituacion().equals(lote.SITUACION_RECIBIDO)){
			lote.setSituacion(lote.SITUACION_VERIFICADO);
			for (LoteDetalle item : lote.getLoteDetalle()) {
				item.setCantidadVerificada(item.getCantidadRecibida());
			}
			RequestContext.getCurrentInstance().update(":frm_RP");
		    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, localeSelector.getMensaje("comun.exito.importado"), ""));
		}
	}

	public void preparaItem(){
		lotesDetalles = new LoteDetalle();
	}
}

